home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / utilities / cli / move3712.lha / Move / Move.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-27  |  32.7 KB  |  1,362 lines

  1. /*
  2. Auto:        sc <file>
  3. Auto:        Protect Move P ADD
  4. */
  5.  
  6. /* $Revision Header built automatically *************** (do not edit) ************
  7. **
  8. ** © Copyright by GuntherSoft
  9. **
  10. ** File             : SnakeSYS:CPrgs/Utils/Move.c
  11. ** Created on       : Wednesday, 11.08.93 15:01:14
  12. ** Created by       : Kai Iske
  13. ** Current revision : V37.12
  14. **
  15. **
  16. ** Purpose
  17. ** -------
  18. **   - Small move utility which supports wildcards and doesn`t use
  19. **     Rename() nor Copy() nor anything similar...
  20. **
  21. ** Revision V37.12
  22. ** --------------
  23. ** created on Dienstag, 24.01.95 15:50:26  by  Kai Iske.   LogMessage :
  24. **  -*-  changed on Freitag, 27.01.95 13:21:20  by  Kai Iske.   LogMessage :
  25. **   - Same Volume detection method, didn`t always work, so
  26. **     Move didn`t try to Rename() all the time. Furthermore
  27. **     fixes concerning last release didn`t work (Move pic? pics)
  28. **  -*-  created on Dienstag, 24.01.95 15:50:26  by  Kai Iske.   LogMessage :
  29. **   - Technically un-pured Move, while using global LibBase to DOS
  30. **     (fixed for this release. Move is really PURE, again)
  31. **
  32. ** Revision V37.11
  33. ** ---------------
  34. ** created on Monday, 30.05.94 09:20:04  by  Kai Iske.   LogMessage :
  35. **  -*-  changed on Donnerstag, 12.01.95 13:26:43  by  Kai Iske.   LogMessage :
  36. **   - Changed version numbering to official scheme
  37. **  -*-  changed on Mittwoch, 11.01.95 11:04:23  by  Kai Iske.   LogMessage :
  38. **   - One couldn`t move the entire contents of a directory
  39. **     to a dir within that directory (eg. Move #? Dummy)
  40. **  -*-  changed on Mittwoch, 11.01.95 11:03:55  by  Kai Iske.   LogMessage :
  41. **   - One couldn`t move directories, if the destination dirs
  42. **     already existed (eg. Move Dummy1 Dummy2 t:; if Dummy1
  43. **     and Dummy2 both existed in t:)
  44. **  -*-  changed on Montag, 05.09.94 23:16:13  by  Kai Iske.   LogMessage :
  45. **   - OldWindow and HitMask vars weren`t preset to 0
  46. **     (Reported by : Christian Buchner)
  47. **  -*-  created on Monday, 30.05.94 09:20:04  by  Kai Iske.   LogMessage :
  48. **   - When one issued something like this "Move #? dummy/",
  49. **     Move stopped when trying to move dummy to itself ;) Fixed
  50. **
  51. ** Revision V1.10
  52. ** --------------
  53. ** created on Sunday, 06.03.94 16:57:29  by  Kai Iske.   LogMessage :
  54. **  -*-  created on Sunday, 06.03.94 16:57:29  by  Kai Iske.   LogMessage :
  55. **   - Move didn`t end up some operations with a "moved" string,
  56. **     thus leading to corrupted display
  57. **     (Reported by : Albert-Jan Brouwer)
  58. **   - One still couldn`t rename a directory
  59. **     (Reported by : Albert-Jan Brouwer)
  60. **
  61. ** Revision V1.9
  62. ** --------------
  63. ** created on Saturday, 26.02.94 14:15:24  by  Kai Iske.   LogMessage :
  64. **  -*-  changed on Saturday, 26.02.94 14:29:20  by  Kai Iske.   LogMessage :
  65. **   - On recursive moves, Move will indent the output according to
  66. **     recursion depth. This is for better readability
  67. **  -*-  changed on Saturday, 26.02.94 14:19:22  by  Kai Iske.   LogMessage :
  68. **   - Move will refuse to move a dir to itself now.
  69. **  -*-  created on Saturday, 26.02.94 14:15:24  by  Kai Iske.   LogMessage :
  70. **   - One couldn`t move a dir to another dir on the same device
  71. **
  72. ** Revision V1.8
  73. ** --------------
  74. ** created on Sunday, 19.12.93 01:44:05  by  Kai Iske.   LogMessage :
  75. **  -*-  changed on Sunday, 19.12.93 01:47:54  by  Kai Iske.   LogMessage :
  76. **   - Added PURE information to Doc, since Move really is pure
  77. **     (Suggested by : Albert-Jan Brouver)
  78. **  -*-  changed on Sunday, 19.12.93 01:46:23  by  Kai Iske.   LogMessage :
  79. **   - Due to the move-renaming bug one couldn`t rename a dir
  80. **     an Assign was put on.
  81. **     (Reported by : Albert-Jan Brouver)
  82. **  -*-  created on Sunday, 19.12.93 01:44:05  by  Kai Iske.   LogMessage :
  83. **   - Fixed move-renaming of directories.
  84. **     (Reported by : Albert-Jan Brouver)
  85. **   - Move had some severe problems recursively moving
  86. **     the contents of a directory
  87. **
  88. ** Revision V1.7
  89. ** --------------
  90. ** created on Saturday, 04.12.93 23:19:03  by  Kai Iske.   LogMessage :
  91. **  -*-  changed on Saturday, 04.12.93 23:26:25  by  Kai Iske.   LogMessage :
  92. **   - Error while moving to a "device full" disk
  93. **     (Reported by : Chris Conger)
  94. **  -*-  created on Saturday, 04.12.93 23:19:03  by  Kai Iske.   LogMessage :
  95. **   - FileName length-bug fixed
  96. **     (Reported by : Juergen Lang)
  97. **   - Recompiled using SAS 6.50
  98. **   - Stack usage reduced
  99. **
  100. ** Revision V1.6
  101. ** --------------
  102. ** created on Friday, 15.10.93 15:51:13  by  Kai Iske.   LogMessage :
  103. **  -*-  changed on Saturday, 16.10.93 15:17:29  by  Kai Iske.   LogMessage :
  104. **   - Move got screwed up, when attempting to move a
  105. **     zero size file
  106. **  -*-  changed on Friday, 15.10.93 16:03:35  by  Kai Iske.   LogMessage :
  107. **   - Added Buffer Keyword to specify the maximum buffer
  108. **     size for an inter device move. Normally Move would have used
  109. **     the max amount of available free memory in order to
  110. **     accomplish the move, or the size needed by the file...
  111. **     (Suggested by : Christof Damian)
  112. **  -*-  created on Friday, 15.10.93 15:51:13  by  Kai Iske.   LogMessage :
  113. **   - One couldn`t rename a file using move, because the
  114. **     "destination" file was removed before doing the rename,
  115. **     ie. the source file was deleted.
  116. **     (Reported by : Chris Conger)
  117. **
  118. ** Revision V1.5
  119. ** --------------
  120. ** created on Tuesday, 05.10.93 01:42:53  by  Kai Iske.   LogMessage :
  121. **  -*-  changed on Tuesday, 05.10.93 02:03:22  by  Kai Iske.   LogMessage :
  122. **   - Freed the FileInfoBlock _BEFORE_ setting the Bits, Comment
  123. **     etc. This lead to MungWall hits (of course it did)
  124. **     (Reported by Nico Francois)
  125. **  -*-  created on Tuesday, 05.10.93 01:42:53  by  Kai Iske.   LogMessage :
  126. **   - Exidentially called one ExAll() without ED_SIZE
  127. **     This lead to some calls to DoTheMove without the Size set ;)
  128. **     (Reported by  Karsten Weiss)
  129. **
  130. ** Revision V1.4
  131. ** --------------
  132. ** created on Friday, 01.10.93 16:55:15  by  Kai Iske.   LogMessage :
  133. **  -*-  created on Friday, 01.10.93 16:55:15  by  Kai Iske.   LogMessage :
  134. **   - Now uses Rename() when source and dest are on the same
  135. **     device. This is faster ;) Why haven`t I thought of that
  136. **     earlier ??? ;)
  137. **
  138. ** Revision V1.3
  139. ** --------------
  140. ** created on Wednesday, 25.08.93 16:32:43  by  Kai Iske.   LogMessage :
  141. **   - UnLock Problem solved when doing recursive Dir-Moves
  142. **     This bug lead to "Object in use" error messages
  143. **
  144. ** Revision V1.2
  145. ** --------------
  146. ** created on Tuesday, 17.08.93 22:48:38  by  Kai Iske.   LogMessage :
  147. **   - Added CTRL-C checking
  148. **   - Added FORCE Flag in order to move read/deleteprotected or
  149. **     to overwrite a delete/writeprotected files
  150. **
  151. ** Revision V1.1
  152. ** --------------
  153. ** created on Monday, 16.08.93 22:53:34  by  Kai Iske.   LogMessage :
  154. **   - Added well known CLONE, DATES, COM, NOPRO,
  155. **     QUIET and NOREQ options also used by e.g. Rename
  156. **
  157. ** Revision V1.0
  158. ** --------------
  159. ** created on Wednesday, 11.08.93 15:01:14  by  Kai Iske.   LogMessage :
  160. **     --- Initial release ---
  161. **
  162. *********************************************************************************/
  163. #define REVISION "37.12"
  164. #define REVDATE  "27.01.95"
  165. #define REVTIME  "13:21:20"
  166. #define AUTHOR   "Kai Iske"
  167. #define VERNUM   37
  168. #define REVNUM   12
  169.  
  170. #include    <string.h>
  171. #include    <stdlib.h>
  172. #include    <exec/types.h>
  173. #include    <proto/exec.h>
  174. #include    <proto/dos.h>
  175. #include    <exec/memory.h>
  176. #include    <exec/execbase.h>
  177. #include    <dos/exall.h>
  178. #include    <dos/dos.h>
  179. #include    <dos/dosextens.h>
  180.  
  181.  
  182.  
  183.  
  184.  
  185. /**********************************************************************/
  186. /*                         Defines for Flags                          */
  187. /**********************************************************************/
  188. #define    CLONE        0x0001
  189. #define    DATES        0x0002
  190. #define    NOPRO        0x0004
  191. #define    COM        0x0008
  192. #define    QUIET        0x0010
  193. #define    FORCE        0x0020
  194.  
  195. #define    WATCHSIGS    SIGBREAKF_CTRL_C
  196.  
  197.  
  198.  
  199. /**********************************************************************/
  200. /*                      Static char definitions                       */
  201. /**********************************************************************/
  202. static    const char    *Version    = "$VER: Move "REVISION" ("REVDATE")\0";
  203. static    const char    *Template    = "FROM/M,TO/A,CLONE/S,DATES/S,NOPRO/S,COM/S,QUIET/S,NOREQ/S,FORCE/S,BUFFER/N/K";
  204. enum    {FROM_ARG, TO_ARG, CLONE_ARG, DATES_ARG, NOPRO_ARG, COM_ARG, QUIET_ARG, NOREQ_ARG, FORCE_ARG, BUFFER_ARG, LAST_ARG};
  205.  
  206.  
  207.  
  208. /**********************************************************************/
  209. /*                             Prototypes                             */
  210. /**********************************************************************/
  211. int        __saveds DoMove(void);
  212. static    BOOL    __stdargs DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer, ULONG RecDepth, struct DosLibrary *DOSBase);
  213. static    BOOL    __stdargs DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer, struct DosLibrary *DOSBase);
  214.  
  215.  
  216.  
  217.  
  218. /**********************************************************************/
  219. /*                          The main program                          */
  220. /**********************************************************************/
  221. int __saveds DoMove(void)
  222. {
  223.     struct    FileInfoBlock    *FIB;
  224.     struct    ExecBase    *SysBase    = *((struct ExecBase **)0x4L);
  225.     struct    DosLibrary    *DOSBase;
  226.     struct    Process        *MyProc        = (struct Process *)SysBase->ThisTask;
  227.     struct    RDArgs        *RDArgs;
  228.     struct    ExAllControl    *EAC;
  229.     struct    ExAllData    *EAB, *EAD;
  230.     APTR            *Args,
  231.                 *OldWindow    = NULL;
  232.     BPTR            DirLock,
  233.                 OutHandle;
  234.     char            **FromPtr;
  235.     char            *ToPtr;
  236.     char            *Pattern;
  237.     char            *PathName    = NULL;
  238.     char            *Buffer        = NULL;
  239.     LONG            HitMask        = 0;
  240.     UWORD            NumFrom        = 0,
  241.                 PatternType,
  242.                 CopyFlags    = 0;
  243.     ULONG            MaxBuffer    = 0;
  244.     BOOL            PatternFrom,
  245.                 GoOn        = FALSE,
  246.                 Scanning;
  247.  
  248.  
  249.  
  250.  
  251.         // Ignore startup from WB
  252.  
  253.     if(!(MyProc->pr_CLI))
  254.     {
  255.         struct    Message    *MyMsg;
  256.  
  257.         WaitPort(&MyProc->pr_MsgPort);
  258.         MyMsg = GetMsg(&MyProc->pr_MsgPort);
  259.         Disable();
  260.         ReplyMsg(MyMsg);
  261.         return(10);
  262.     }
  263.  
  264.         // Do the wild thing
  265.  
  266.     if((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37)))
  267.     {
  268.             // Allocate buffers
  269.  
  270.         if((Pattern = AllocVec(1024, MEMF_CLEAR)) && (PathName = AllocVec(1024, MEMF_CLEAR)) && (Buffer = AllocVec(1024, MEMF_CLEAR)))
  271.         {
  272.             if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
  273.             {
  274.                     // Get buffer for ReadArgs()
  275.  
  276.                 if((Args = AllocVec((LAST_ARG * sizeof(ULONG)), MEMF_CLEAR)))
  277.                 {
  278.                         // Get structure for ExAll()
  279.  
  280.                     if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  281.                     {
  282.                             // Get buffer for ExAll()
  283.  
  284.                         if((EAB = AllocVec((sizeof(struct ExAllData)*20), MEMF_CLEAR)))
  285.                         {
  286.                                 // Parse commandline
  287.  
  288.                             if((RDArgs = ReadArgs((char *)Template, (LONG *)Args, NULL)))
  289.                             {
  290.                                     // From and to really there ??
  291.  
  292.                                 if(Args[FROM_ARG] && Args[TO_ARG])
  293.                                 {
  294.                                         // A O.K. so far
  295.  
  296.                                     GoOn        = TRUE;
  297.  
  298.                                         // Get output handle
  299.  
  300.                                     OutHandle    = Output();
  301.  
  302.                                         // Get Flags
  303.  
  304.                                     if(Args[CLONE_ARG])
  305.                                         CopyFlags    |=    CLONE;
  306.                                     if(Args[DATES_ARG])
  307.                                         CopyFlags    |=    DATES;
  308.                                     if(Args[NOPRO_ARG])
  309.                                         CopyFlags    |=    NOPRO;
  310.                                     if(Args[COM_ARG])
  311.                                         CopyFlags    |=    COM;
  312.                                     if(Args[QUIET_ARG])
  313.                                         CopyFlags    |=    QUIET;
  314.                                     if(Args[FORCE_ARG])
  315.                                         CopyFlags    |=    FORCE;
  316.                                     if(Args[BUFFER_ARG])
  317.                                         MaxBuffer    =    *((ULONG *)Args[BUFFER_ARG]) * 1024;
  318.  
  319.                                         // Check for NOREQ Option
  320.  
  321.                                     if(Args[NOREQ_ARG])
  322.                                     {
  323.                                         OldWindow        = MyProc->pr_WindowPtr;
  324.                                         MyProc->pr_WindowPtr    = (void *)(-1L);
  325.                                     }
  326.  
  327.                                         // Get pointers to Files
  328.  
  329.                                     FromPtr    = (char **)Args[FROM_ARG];
  330.                                     ToPtr    = (char *)Args[TO_ARG];
  331.  
  332.                                         // Count FROM entries
  333.  
  334.                                     while(*FromPtr++)
  335.                                         NumFrom++;
  336.  
  337.                                         // Restore FromPtr
  338.  
  339.                                     FromPtr    = (char **)Args[FROM_ARG];
  340.  
  341.                                         // Set pattern if there are more than 1
  342.                                         // FROM files or if the only FROM file
  343.                                         // is a pattern
  344.  
  345.                                     if(NumFrom > 1)
  346.                                         PatternFrom = TRUE;
  347.                                     else
  348.                                         PatternFrom = ParsePatternNoCase(*FromPtr, Pattern, 1024);
  349.  
  350.                                         // If a pattern is used, check
  351.                                         // whether the dest really is a dir
  352.  
  353.                                     if(PatternFrom)
  354.                                     {
  355.                                             // Try to obtain a lock
  356.  
  357.                                         if((DirLock = Lock(ToPtr, ACCESS_READ)))
  358.                                         {
  359.                                                 // Check file
  360.  
  361.                                             if(Examine(DirLock, FIB))
  362.                                             {
  363.                                                     // Get type of destination entry
  364.  
  365.                                                 GoOn = (FIB->fib_DirEntryType >= 0);
  366.  
  367.                                                     // If it`s not a directory (multiple files are to be moved)
  368.                                                     // issue an error
  369.  
  370.                                                 if(!GoOn)
  371.                                                     FPuts(OutHandle, "\nMove : Multiple files may not be moved to a single file\n");
  372.                                             }
  373.                                             else
  374.                                             {
  375.                                                     // Examine() failed -> Abort
  376.  
  377.                                                 GoOn = FALSE;
  378.                                                 PrintFault(IoErr(), "\nMove ");
  379.                                             }
  380.  
  381.                                                 // Unlock CheckDir
  382.  
  383.                                             UnLock(DirLock);
  384.                                         }
  385.                                         else
  386.                                         {
  387.                                                 // If lock failed issue an error
  388.  
  389.                                             PrintFault(IoErr(), "\nMove ");
  390.                                             GoOn = FALSE;
  391.                                         }
  392.                                     }
  393.  
  394.  
  395.  
  396.                                         // Loop for all source files
  397.  
  398.                                     while(NumFrom && GoOn)
  399.                                     {
  400.                                             // Check for CTRL-C
  401.  
  402.                                         if(GoOn)
  403.                                             HitMask    = CheckSignal(WATCHSIGS);
  404.  
  405.                                         if(!HitMask && GoOn)
  406.                                         {
  407.                                                 // Check if this source is a pattern
  408.  
  409.                                             strcpy(Buffer, FilePart(*FromPtr));
  410.                                             strupr(Buffer);
  411.                                             PatternType = ParsePatternNoCase(Buffer, Pattern, 1024);
  412.  
  413.                                                 // It is a pattern
  414.  
  415.                                             if(PatternType == 1)
  416.                                             {
  417.                                                     // Create name of source
  418.  
  419.                                                 strcpy(Buffer, *FromPtr);
  420.                                                 *PathPart(Buffer)    = '\0';
  421.  
  422.                                                     // Get Lock for Source - Directory
  423.  
  424.                                                 if((DirLock = Lock(Buffer, ACCESS_READ)))
  425.                                                 {
  426.                                                         // Setup ExAllControl-Structure
  427.  
  428.                                                     EAC->eac_LastKey    = 0L;
  429.                                                     EAC->eac_MatchString    = Pattern;
  430.                                                     EAC->eac_MatchFunc    = NULL;
  431.  
  432.                                                     do
  433.                                                     {
  434.                                                             // Check for CTRL-C
  435.  
  436.                                                         if(GoOn)
  437.                                                             HitMask = CheckSignal(WATCHSIGS);
  438.  
  439.                                                         if(HitMask)
  440.                                                             GoOn = FALSE;
  441.  
  442.                                                             // Scan directory
  443.  
  444.                                                         Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
  445.  
  446.                                                             // Issue Error
  447.  
  448.                                                         if(GoOn && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  449.                                                         {
  450.                                                             PrintFault(IoErr(), "\nMove ");
  451.                                                             GoOn = FALSE;
  452.                                                         }
  453.  
  454.                                                             // End of Dir reached
  455.  
  456.                                                         if(EAC->eac_Entries == 0)
  457.                                                             Scanning = FALSE;
  458.                                                         else if(GoOn)
  459.                                                         {
  460.                                                             EAD    = EAB;
  461.  
  462.                                                             do
  463.                                                             {
  464.                                                                     // Check for CTRL-C
  465.  
  466.                                                                 if(GoOn)
  467.                                                                     HitMask = CheckSignal(WATCHSIGS);
  468.  
  469.                                                                 if(!HitMask && GoOn)
  470.                                                                 {
  471.                                                                         // Create filename for this file to be moved
  472.  
  473.                                                                     strcpy(PathName, *FromPtr);
  474.                                                                     *PathPart(PathName)    = '\0';
  475.                                                                     AddPart(PathName, EAD->ed_Name, 1024);
  476.  
  477.                                                                         // Move file
  478.  
  479.                                                                     GoOn    = DoTheMove(PathName, ToPtr, TRUE, OutHandle, EAD->ed_Type, EAD->ed_Size, CopyFlags, &HitMask, MaxBuffer, 1, DOSBase);
  480.  
  481.                                                                     EAD    = EAD->ed_Next;
  482.                                                                 }
  483.                                                                 else
  484.                                                                     GoOn = FALSE;
  485.  
  486.                                                             } while(EAD && GoOn);
  487.                                                         }
  488.                                                     } while(Scanning);
  489.  
  490.                                                         // Unlock source directory
  491.  
  492.                                                     UnLock(DirLock);
  493.                                                 }
  494.                                                 else
  495.                                                 {
  496.                                                         // Issue error, if dir could not be locked
  497.  
  498.                                                     PrintFault(IoErr(), "\nMove ");
  499.                                                     GoOn    = FALSE;
  500.                                                 }
  501.                                             }
  502.                                                 // No pattern
  503.  
  504.                                             else if(PatternType == 0)
  505.                                             {
  506.                                                     // Try to lock source file/dir
  507.  
  508.                                                 if((DirLock = Lock(*FromPtr, ACCESS_READ)))
  509.                                                 {
  510.                                                         // Examine this lock
  511.  
  512.                                                     if(Examine(DirLock, FIB))
  513.                                                     {
  514.                                                             // Unlock directory and do the move
  515.  
  516.                                                         UnLock(DirLock);
  517.                                                         GoOn    = DoTheMove(*FromPtr, ToPtr, TRUE, OutHandle, FIB->fib_DirEntryType, FIB->fib_Size, CopyFlags, &HitMask, MaxBuffer, 1, DOSBase);
  518.                                                     }
  519.                                                     else
  520.                                                     {
  521.                                                             // Issue error on failed Examine()
  522.  
  523.                                                         PrintFault(IoErr(), "\nMove ");
  524.                                                         GoOn = FALSE;
  525.                                                         UnLock(DirLock);
  526.                                                     }
  527.                                                 }
  528.                                                 else
  529.                                                 {
  530.                                                         // No Lock() no more moves
  531.  
  532.                                                     PrintFault(IoErr(), "\nMove ");
  533.                                                     GoOn = FALSE;
  534.                                                 }
  535.                                             }
  536.  
  537.                                                 // Error condition
  538.  
  539.                                             else
  540.                                             {
  541.                                                 PrintFault(IoErr(), "\nMove ");
  542.                                                 GoOn = FALSE;
  543.                                             }
  544.  
  545.                                             NumFrom--;
  546.                                             FromPtr++;
  547.                                         }
  548.                                         else
  549.                                             GoOn    = FALSE;
  550.                                     }
  551.                                 }
  552.  
  553.                                     // Free ReadArgs
  554.  
  555.                                 FreeArgs(RDArgs);
  556.                             }
  557.                             else
  558.                                 PrintFault(IoErr(), "\nMove ");
  559.  
  560.                                 // Free ExAll-Buffer
  561.  
  562.                             FreeVec(EAB);
  563.                         }
  564.                         else
  565.                             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  566.  
  567.                             // Free ExAllControl Structure
  568.  
  569.                         FreeDosObject(DOS_EXALLCONTROL, (void *)EAC);
  570.                     }
  571.                     else
  572.                         PrintFault(IoErr(), "\nMove ");
  573.  
  574.                         // Free Argument Buffer
  575.  
  576.                     FreeVec(Args);
  577.                 }
  578.                 else
  579.                     PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  580.  
  581.                 FreeVec(FIB);
  582.             }
  583.             else
  584.                 PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  585.         }
  586.         else
  587.             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  588.  
  589.  
  590.             // Free allocated buffers
  591.  
  592.         if(Pattern)
  593.             FreeVec(Pattern);
  594.  
  595.         if(PathName)
  596.             FreeVec(PathName);
  597.  
  598.         if(Buffer)
  599.             FreeVec(Buffer);
  600.  
  601.  
  602.             // Check for Abort-Signals
  603.  
  604.         if(HitMask && !(CopyFlags & QUIET))
  605.         {
  606.                 // Display appropriate message
  607.  
  608.             if(HitMask & SIGBREAKF_CTRL_C)
  609.                 FPuts(OutHandle, "\nMove ^C...\n");
  610.         }
  611.  
  612.             // Close DOSLibrary
  613.  
  614.         CloseLibrary((struct Library *)DOSBase);
  615.     }
  616.  
  617.         // Restore old window pointer (if any)
  618.  
  619.     if(OldWindow)
  620.         MyProc->pr_WindowPtr    = OldWindow;
  621.  
  622.  
  623.         // Depending on this flag return appropriate return code
  624.  
  625.     if(GoOn)
  626.         return(0);
  627.     else
  628.         return(10);
  629. }
  630.  
  631.  
  632.  
  633.  
  634. /**********************************************************************/
  635. /*                            Do the move                             */
  636. /**********************************************************************/
  637. static BOOL __stdargs DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer, ULONG RecDepth, struct DosLibrary *DOSBase)
  638. {
  639.     struct    ExAllControl    *EAC;
  640.     struct    ExAllData    *EAB,
  641.                 *EAD;
  642.     struct    DevProc        *FromProc,
  643.                 *ToProc;
  644.     char    *NewDir;
  645.     char    *Buffer        = NULL;
  646.     char    *ToDir        = NULL;
  647.     char    *DispBuff    = NULL;
  648.     UWORD    Len;
  649.     BPTR    DirLock;
  650.     BOOL    RetVal        = TRUE,
  651.         Scanning,
  652.         DoRename    = FALSE,
  653.         MoveDirToSame    = FALSE,
  654.         Skipped        = FALSE;
  655.  
  656.  
  657.         // Try to allocate buffers
  658.  
  659.     if((NewDir = AllocVec(1024, MEMF_CLEAR)) && (Buffer = AllocVec(1024, MEMF_CLEAR)) && (ToDir = AllocVec(1024, MEMF_CLEAR)) && (DispBuff = AllocVec(1024, MEMF_CLEAR)))
  660.     {
  661.             // Is it a directory ???
  662.             // If yes, recursively loop for all entries within dir
  663.  
  664.         if(Type >= 0)
  665.         {
  666.             strcpy(Buffer, FromFile);
  667.  
  668.                 // Get length of from name
  669.  
  670.             Len    = strlen(Buffer);
  671.  
  672.                 // Really got a from name ?!?
  673.  
  674.             if(Len)
  675.             {
  676.                 if(Buffer[Len - 1] == '/')
  677.                     Buffer[Len - 1] = '\0';
  678.  
  679.                     // Copy dest name to buffer
  680.  
  681.                 strcpy(NewDir, ToPath);
  682.  
  683.  
  684.                     // May we simply Rename()?
  685.  
  686.                 FromProc    = GetDeviceProc(Buffer, NULL);
  687.                 ToProc        = GetDeviceProc(NewDir, NULL);
  688.  
  689.                 if(FromProc && ToProc)
  690.                     DoRename    = (FromProc->dvp_Port == ToProc->dvp_Port);
  691.  
  692.                 if(FromProc)
  693.                     FreeDeviceProc(FromProc);
  694.  
  695.                 if(ToProc)
  696.                     FreeDeviceProc(ToProc);
  697.  
  698.  
  699.                     // Check for dir moving to itself...
  700.                     // ...and for renaming
  701.  
  702.                 if((DirLock = Lock(Buffer, ACCESS_READ)))
  703.                 {
  704.                     BPTR    TestLock;
  705.  
  706.                     if((TestLock = Lock(NewDir, ACCESS_READ)))
  707.                     {
  708.                             // Renaming a directory ???
  709.  
  710.                         MoveDirToSame    = (SameLock(DirLock, TestLock) == LOCK_SAME);
  711.  
  712.                         UnLock(TestLock);
  713.                     }
  714.  
  715.                     UnLock(DirLock);
  716.                 }
  717.  
  718.  
  719.                     // Ok, we are to move
  720.                     // If a pattern is used print the name of the dir to be moved
  721.  
  722.                 if(PatternFrom && !(CopyFlags & QUIET))
  723.                 {
  724.                     int    i;
  725.  
  726.                         // Prepend number of spaces according to recursion depth
  727.  
  728.                     for(i = 0; i < RecDepth; i++)
  729.                         DispBuff[i]    = ' ';
  730.                     DispBuff[i]    = '\0';
  731.  
  732.                     strcat(DispBuff, FromFile);
  733.                     strcat(DispBuff, "...");
  734.                     Write(OutHandle, " ", 1);
  735.                     Write(OutHandle, DispBuff, strlen(DispBuff));
  736.                 }
  737.  
  738.  
  739.                     // Destination directory available ???
  740.                     // If so, we are to move to that directory
  741.                     // Otherwise, we`ll simply rename
  742.  
  743.                 if((DirLock = Lock(NewDir, ACCESS_READ)))
  744.                 {
  745.                     UnLock(DirLock);
  746.  
  747.                         // Add name of from directory
  748.  
  749.                     if(!MoveDirToSame)
  750.                         AddPart(NewDir, FilePart(Buffer), 1024);
  751.                 }
  752.  
  753.  
  754.                     // Simple rename; no cross-device move ?!?
  755.  
  756.                 if(DoRename)
  757.                 {
  758.                     BOOL    DoTheRename    = TRUE;
  759.  
  760.                         // Trying to rename a directory?
  761.                         // Only allowed when not in pattern or multimode
  762.  
  763.                     if(MoveDirToSame)
  764.                         DoTheRename    = !PatternFrom;
  765.  
  766.                         // Still rename the directory?
  767.  
  768.                     if(DoTheRename)
  769.                     {
  770.                         BPTR    TestLock;
  771.  
  772.                             // Destination is already there?
  773.                             // If so, only move contents
  774.  
  775.                         if((TestLock = Lock(NewDir, ACCESS_READ)))
  776.                         {
  777.                             DoRename    = FALSE;
  778.                             UnLock(TestLock);
  779.                         }
  780.                         else
  781.                         {
  782.                                 // Do the rename
  783.  
  784.                             if(!Rename(Buffer, NewDir))
  785.                             {
  786.                                 PrintFault(IoErr(), "\nMove ");
  787.                                 RetVal = FALSE;
  788.                             }
  789.                         }
  790.                     }
  791.                     else
  792.                         Skipped    = TRUE;
  793.                 }
  794.  
  795.                 if(!DoRename)
  796.                 {
  797.                         // Clone directory name of source
  798.  
  799.                     strcpy(ToDir, Buffer);
  800.  
  801.                         // Try to lock directory or
  802.                         // create it, if not existent
  803.  
  804.                     if(!(DirLock = Lock(NewDir, ACCESS_READ)))
  805.                     {
  806.                         if((DirLock = CreateDir(NewDir)) && PatternFrom && !(CopyFlags & QUIET))
  807.                             Write(OutHandle, " [created]...", 13);
  808.                     }
  809.  
  810.                         // Got the destination directory ???
  811.  
  812.                     if(DirLock)
  813.                     {
  814.                             // Unlock Directory
  815.  
  816.                         UnLock(DirLock);
  817.  
  818.                             // Lock sourcedirectory
  819.  
  820.                         if((DirLock = Lock(Buffer, ACCESS_READ)))
  821.                         {
  822.                                 // Get ExAll Control for recursive directory search
  823.  
  824.                             if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  825.                             {
  826.                                     // Allocate buffer for move
  827.  
  828.                                 if((EAB = AllocVec((20*sizeof(struct ExAllData)), MEMF_CLEAR)))
  829.                                 {
  830.                                     EAC->eac_LastKey    = 0L;
  831.                                     EAC->eac_MatchString    = NULL;
  832.                                     EAC->eac_MatchFunc    = NULL;
  833.  
  834.                                     do
  835.                                     {
  836.                                             // Check for CTRL-C
  837.  
  838.                                         if(RetVal)
  839.                                             (*HitMask) = CheckSignal(WATCHSIGS);
  840.  
  841.                                         if((*HitMask))
  842.                                             RetVal = FALSE;
  843.  
  844.                                             // Scan directory for entries
  845.  
  846.                                         Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
  847.  
  848.                                             // Check for an error
  849.  
  850.                                         if(RetVal && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
  851.                                         {
  852.                                             PrintFault(IoErr(), "\nMove ");
  853.                                             RetVal = FALSE;
  854.                                         }
  855.  
  856.                                             // End of Dir reached
  857.  
  858.                                         if(EAC->eac_Entries == 0)
  859.                                             Scanning = FALSE;
  860.                                         else if(RetVal)
  861.                                         {
  862.                                             EAD = EAB;
  863.  
  864.                                             do
  865.                                             {
  866.                                                     // Check for CTRL-C
  867.  
  868.                                                 if(RetVal)
  869.                                                     (*HitMask) = CheckSignal(WATCHSIGS);
  870.  
  871.                                                 if(!(*HitMask) && RetVal)
  872.                                                 {
  873.                                                         // Create filename of source
  874.  
  875.                                                     strcpy(Buffer, FromFile);
  876.                                                     AddPart(Buffer, EAD->ed_Name, 1024);
  877.  
  878.                                                         // And start recursion
  879.  
  880.                                                     RetVal = DoTheMove(Buffer, NewDir, FALSE, OutHandle, EAD->ed_Type, EAD->ed_Size, CopyFlags, HitMask, MaxBuffer, RecDepth + 1, DOSBase);
  881.  
  882.                                                         // Loop for all entries
  883.  
  884.                                                     EAD = EAD->ed_Next;
  885.                                                 }
  886.                                                 else
  887.                                                     RetVal = FALSE;
  888.  
  889.                                             } while(EAD && RetVal);
  890.                                         }
  891.                                     } while(Scanning);
  892.  
  893.                                         // Free ExAll Buffer
  894.  
  895.                                     FreeVec(EAB);
  896.                                 }
  897.                                 else
  898.                                 {
  899.                                     PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  900.                                     RetVal = FALSE;
  901.                                 }
  902.  
  903.                                     // Free ExAllControl Structure
  904.  
  905.                                 FreeDosObject(DOS_EXALLCONTROL, EAC);
  906.                             }
  907.                             else
  908.                             {
  909.                                 PrintFault(IoErr(), "\nMove ");
  910.                                 RetVal = FALSE;
  911.                             }
  912.  
  913.                             UnLock(DirLock);
  914.                         }
  915.                         else
  916.                         {
  917.                             PrintFault(IoErr(), "\nMove ");
  918.                             RetVal = FALSE;
  919.                         }
  920.                     }
  921.                     else
  922.                     {
  923.                         PrintFault(IoErr(), "\nMove ");
  924.                         RetVal = FALSE;
  925.                     }
  926.                 }
  927.  
  928.                     // Ok, this dir was moved (no rename), so remove it
  929.  
  930.                 if(RetVal && !DoRename)
  931.                 {
  932.                         // With force mode set on,
  933.                         // First make dir deletable
  934.  
  935.                     if(CopyFlags & FORCE)
  936.                         SetProtection(ToDir, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  937.  
  938.                         // Delete directory
  939.  
  940.                     if(!DeleteFile(ToDir))
  941.                     {
  942.                         PrintFault(IoErr(), "\nMove ");
  943.                         RetVal = FALSE;
  944.                     }
  945.                 }
  946.  
  947.                     // Display "moved" message
  948.  
  949.                 if(PatternFrom && RetVal && !(CopyFlags & QUIET))
  950.                 {
  951.                     if(!Skipped)
  952.                         FPuts(OutHandle, " moved\n");
  953.                     else
  954.                         FPuts(OutHandle, " skipped\n");
  955.                 }
  956.             }
  957.         }
  958.         else
  959.         {
  960.                 // Ok, we are to move
  961.                 // If a pattern is used print the name of the file to be moved
  962.  
  963.             if(PatternFrom && !(CopyFlags & QUIET))
  964.             {
  965.                 int    i;
  966.  
  967.                     // Prepend number of spaces according to recursion depth
  968.  
  969.                 for(i = 0; i < RecDepth; i++)
  970.                     DispBuff[i]    = ' ';
  971.                 DispBuff[i]    = '\0';
  972.  
  973.                 strcat(DispBuff, FromFile);
  974.                 strcat(DispBuff, "...");
  975.                 Write(OutHandle, " ", 1);
  976.                 Write(OutHandle, DispBuff, strlen(DispBuff));
  977.             }
  978.  
  979.                 // On a plain file -> Simply move it
  980.  
  981.             RetVal = DoMoveFile(FromFile, ToPath, Buffer, OutHandle, Size, CopyFlags, HitMask, MaxBuffer, DOSBase);
  982.  
  983.                 // If there was a pattern (or a single directory)
  984.                 // end the Move string
  985.  
  986.             if(PatternFrom && RetVal && !(CopyFlags & QUIET))
  987.             {
  988.                 if(!Skipped)
  989.                     FPuts(OutHandle, " moved\n");
  990.                 else
  991.                     FPuts(OutHandle, " skipped\n");
  992.             }
  993.         }
  994.     }
  995.     else
  996.     {
  997.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  998.         RetVal = FALSE;
  999.     }
  1000.  
  1001.         // De-Allocate buffers
  1002.  
  1003.     if(NewDir)
  1004.         FreeVec(NewDir);
  1005.  
  1006.     if(Buffer)
  1007.         FreeVec(Buffer);
  1008.  
  1009.     if(ToDir)
  1010.         FreeVec(ToDir);
  1011.  
  1012.     if(DispBuff)
  1013.         FreeVec(DispBuff);
  1014.  
  1015.         // Return Code
  1016.  
  1017.     return(RetVal);
  1018. }
  1019.  
  1020.  
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026.  
  1027. /**********************************************************************/
  1028. /*                       Physically move a file                       */
  1029. /**********************************************************************/
  1030. static BOOL __stdargs DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, ULONG Size, UWORD CopyFlags, LONG *HitMask, ULONG MaxBuffer, struct DosLibrary *DOSBase)
  1031. {
  1032.     struct    FileInfoBlock    *FIB;
  1033.     struct    DevProc        *FromProc,
  1034.                 *ToProc;
  1035.     BPTR            InFile,
  1036.                 OutFile;
  1037.     char            *DestName;
  1038.     APTR            CopyBuffer;
  1039.     ULONG            ReadSize,
  1040.                 AvailSize;
  1041.     LONG            InKey        = -1,
  1042.                 OutKey        = -1;
  1043.     BOOL            RetVal        = TRUE,
  1044.                 ErrCpy        = FALSE,
  1045.                 LoopCpy        = TRUE,
  1046.                 DoRename    = FALSE,
  1047.                 RemoveFirst    = FALSE;
  1048.  
  1049.  
  1050.         // Allocate buffer for Destination name
  1051.  
  1052.     if(!(DestName = AllocVec(1024, MEMF_CLEAR)))
  1053.     {
  1054.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  1055.         return(FALSE);
  1056.     }
  1057.  
  1058.     if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
  1059.     {
  1060.  
  1061.         strcpy(DestName, ToPath);
  1062.  
  1063.             // Check, if destfile already exists
  1064.             // If so, check if it`s a dir.
  1065.             // Yes -> Copy with sourcename
  1066.             // No -> Copy with given name
  1067.  
  1068.         if((OutFile = Lock(DestName, ACCESS_READ)))
  1069.         {
  1070.             if(Examine(OutFile, FIB))
  1071.             {
  1072.                     // If dest is a directory move with source name
  1073.  
  1074.                 if(FIB->fib_DirEntryType >= 0)
  1075.                     AddPart(DestName, FilePart(FromFile), 1024);
  1076.                 else
  1077.                 {
  1078.                     OutKey        = ((struct FileLock *)BADDR(OutFile))->fl_Key;
  1079.                     RemoveFirst    = TRUE;
  1080.                 }
  1081.             }
  1082.             else
  1083.             {
  1084.                     // No examine -> Use source filename
  1085.  
  1086.                 AddPart(DestName, FilePart(FromFile), 1024);
  1087.             }
  1088.  
  1089.             UnLock(OutFile);
  1090.         }
  1091.  
  1092.             // Try to lock input file
  1093.  
  1094.         if((InFile = Lock(FromFile, ACCESS_READ)))
  1095.         {
  1096.                 // Get DiskBlock for inputfile
  1097.  
  1098.             InKey    = ((struct FileLock *)BADDR(InFile))->fl_Key;
  1099.  
  1100.                 // Get old protection bits, comment and filedate
  1101.  
  1102.             if(Examine(InFile, FIB))
  1103.             {
  1104.                     // In Force mode -> Force read and delete permissons
  1105.                     // for input file
  1106.  
  1107.                 if(CopyFlags & FORCE)
  1108.                     SetProtection(FromFile, ~(FIBF_OTR_READ|FIBF_OTR_DELETE|FIBF_READ|FIBF_DELETE));
  1109.             }
  1110.             else
  1111.             {
  1112.                 PrintFault(IoErr(), "\nMove ");
  1113.                 RetVal = FALSE;
  1114.             }
  1115.  
  1116.                 // If so, unlock
  1117.  
  1118.             UnLock(InFile);
  1119.         }
  1120.         else
  1121.         {
  1122.             PrintFault(IoErr(), "\nMove ");
  1123.             RetVal = FALSE;
  1124.         }
  1125.  
  1126.             // Can we possibly simple rename the file?
  1127.  
  1128.         FromProc    = GetDeviceProc(FromFile, NULL);
  1129.         ToProc        = GetDeviceProc(ToPath, NULL);
  1130.  
  1131.         if(FromProc && ToProc)
  1132.             DoRename    = (FromProc->dvp_Port == ToProc->dvp_Port);
  1133.  
  1134.         if(FromProc)
  1135.             FreeDeviceProc(FromProc);
  1136.  
  1137.         if(ToProc)
  1138.             FreeDeviceProc(ToProc);
  1139.  
  1140.  
  1141.             // No Rename -> Do the right move ;)
  1142.  
  1143.         if(!DoRename)
  1144.         {
  1145.                 // Open Input file
  1146.  
  1147.             if(RetVal && (InFile = Open(FromFile, MODE_OLDFILE)))
  1148.             {
  1149.                     // Outfile already there ??? and in force mode ???
  1150.  
  1151.                 if((CopyFlags & FORCE) && ((OutFile = Lock(DestName, ACCESS_READ))))
  1152.                 {
  1153.                         // Force delete and write permissons
  1154.  
  1155.                     UnLock(OutFile);
  1156.                     SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  1157.                 }
  1158.  
  1159.  
  1160.                     // Open Output file
  1161.  
  1162.                 if((OutFile = Open(DestName, MODE_NEWFILE)))
  1163.                 {
  1164.                         // Is there any data within the file ???
  1165.  
  1166.                     if(Size)
  1167.                     {
  1168.                             // Get available size of memory
  1169.                             // or take the user`s buffer size into account
  1170.  
  1171.                         AvailSize    = (MaxBuffer != 0) ? MaxBuffer : (AvailMem(MEMF_LARGEST) - 102400);
  1172.                         Size        = (Size > AvailSize) ? AvailSize : Size;
  1173.  
  1174.                             // Loop till we get a buffer
  1175.  
  1176.                         while(Size && !(CopyBuffer = AllocVec(Size, MEMF_CLEAR)))
  1177.                             Size    -= 1024;
  1178.  
  1179.  
  1180.                         if(CopyBuffer)
  1181.                         {
  1182.                                 // Loop for portions of the source file
  1183.  
  1184.                             while(RetVal && LoopCpy)
  1185.                             {
  1186.                                     // Check for CTRL-C
  1187.  
  1188.                                 if(RetVal)
  1189.                                     (*HitMask) = CheckSignal(WATCHSIGS);
  1190.  
  1191.                                 if(!(*HitMask) && RetVal)
  1192.                                 {
  1193.                                         // Read part of file
  1194.  
  1195.                                     if((ReadSize = Read(InFile, CopyBuffer, Size)) > 0)
  1196.                                     {
  1197.                                             // And write it back
  1198.  
  1199.                                         if(Write(OutFile, CopyBuffer, ReadSize) == -1)
  1200.                                         {
  1201.                                             PrintFault(IoErr(), "\nMove ");
  1202.                                             RetVal    = FALSE;
  1203.                                             ErrCpy    = TRUE;
  1204.                                         }
  1205.                                     }
  1206.                                     else
  1207.                                     {
  1208.                                             // EOF ??? -> End copy
  1209.  
  1210.                                         if(ReadSize == 0)
  1211.                                             LoopCpy    = FALSE;
  1212.                                         else
  1213.                                         {
  1214.                                                 // Otherwise issue error
  1215.  
  1216.                                             PrintFault(IoErr(), "\nMove ");
  1217.                                             RetVal    = FALSE;
  1218.                                             ErrCpy    = TRUE;
  1219.                                         }
  1220.                                     }
  1221.                                 }
  1222.                                 else
  1223.                                     RetVal = FALSE;
  1224.                             }
  1225.  
  1226.                             FreeVec(CopyBuffer);
  1227.                         }
  1228.                         else
  1229.                         {
  1230.                             PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  1231.                             RetVal    = FALSE;
  1232.                             ErrCpy    = TRUE;
  1233.                         }
  1234.                     }
  1235.  
  1236.                     Close(OutFile);
  1237.                 }
  1238.                 else
  1239.                 {
  1240.                         // Issue error
  1241.  
  1242.                     PrintFault(IoErr(), "\nMove ");
  1243.                     RetVal = FALSE;
  1244.                 }
  1245.                     // Close InFile
  1246.  
  1247.                 Close(InFile);
  1248.             }
  1249.             else
  1250.             {
  1251.                     // Issue error
  1252.  
  1253.                 PrintFault(IoErr(), "\nMove ");
  1254.                 RetVal = FALSE;
  1255.             }
  1256.         }
  1257.         else
  1258.         {
  1259.                 // If RemoveFirst is not set, check again ;)
  1260.  
  1261.             if(!RemoveFirst)
  1262.             {
  1263.                 if((OutFile = Lock(DestName, ACCESS_READ)))
  1264.                 {
  1265.                     if(Examine(OutFile, FIB))
  1266.                     {
  1267.                             // If dest is a file, delete first
  1268.  
  1269.                         if(FIB->fib_DirEntryType < 0)
  1270.                         {
  1271.                                 // Get Disk block of dest file
  1272.  
  1273.                             OutKey    = ((struct FileLock *)BADDR(OutFile))->fl_Key;
  1274.                             RemoveFirst = TRUE;
  1275.                         }
  1276.                     }
  1277.                     UnLock(OutFile);
  1278.                 }
  1279.             }
  1280.  
  1281.                 // Check if only a rename should be accomplished
  1282.  
  1283.             if(InKey != -1 && OutKey != -1)
  1284.             {
  1285.                 if(InKey == OutKey)
  1286.                     RemoveFirst = FALSE;
  1287.             }
  1288.  
  1289.                 // In Rename() mode, the destination has to be removed first
  1290.  
  1291.             if(RemoveFirst)
  1292.             {
  1293.                     // If dest file is protected check for FORCE flag
  1294.  
  1295.                 if(CopyFlags & FORCE)
  1296.                     SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
  1297.  
  1298.                 if(!DeleteFile(DestName))
  1299.                 {
  1300.                     PrintFault(IoErr(), "\nMove ");
  1301.                     RetVal = FALSE;
  1302.                 }
  1303.             }
  1304.  
  1305.             if(RetVal)
  1306.             {
  1307.                     // Now try to "rename" the file
  1308.  
  1309.                 if(!Rename(FromFile, DestName))
  1310.                 {
  1311.                     PrintFault(IoErr(), "\nMove ");
  1312.                     RetVal = FALSE;
  1313.                 }
  1314.             }
  1315.         }
  1316.  
  1317.             // Error while copying ?? -> Remove Dest file
  1318.  
  1319.         if(ErrCpy)
  1320.         {
  1321.             FPuts(OutHandle, "\nMove : Error while moving; destination removed.\n");
  1322.             DeleteFile(DestName);
  1323.         }
  1324.  
  1325.             // No Error -> Remove Source file
  1326.  
  1327.         if(RetVal && !ErrCpy)
  1328.         {
  1329.             if(!DoRename && !(RetVal = DeleteFile(FromFile)))
  1330.                 PrintFault(IoErr(), "\nMove ");
  1331.             else
  1332.             {
  1333.                     // Set bits etc. as requested
  1334.  
  1335.                 if((CopyFlags & CLONE) || (CopyFlags & DATES))
  1336.                     SetFileDate(DestName, &FIB->fib_Date);
  1337.  
  1338.                 if((CopyFlags & CLONE) || (CopyFlags & COM))
  1339.                     SetComment(DestName, FIB->fib_Comment);
  1340.  
  1341.                 if(((CopyFlags & CLONE) && !(CopyFlags & NOPRO)) || (!(CopyFlags & CLONE) && !(CopyFlags & NOPRO)))
  1342.                     SetProtection(DestName, FIB->fib_Protection);
  1343.             }
  1344.         }
  1345.  
  1346.             // Free FileInfo Block
  1347.  
  1348.         FreeVec(FIB);
  1349.     }
  1350.     else
  1351.     {
  1352.         PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
  1353.         RetVal = FALSE;
  1354.     }
  1355.  
  1356.         // Free buffer for destination name
  1357.  
  1358.     FreeVec(DestName);
  1359.  
  1360.     return(RetVal);
  1361. }
  1362.